<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">

<head>
    <!-- Book generated using mdBook -->
    <meta charset="UTF-8">
    <title>密码矩形 &gt;&lt; Crypto Square - exercisms.io 快速练习</title>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <meta name="description" content="exercisms 的练习，网页版.">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="theme-color" content="#ffffff" />

    <link rel="shortcut icon" href="../favicon.png">
    <link rel="stylesheet" href="../css/variables.css">
    <link rel="stylesheet" href="../css/general.css">
    <link rel="stylesheet" href="../css/chrome.css">
    <link rel="stylesheet" href="../css/print.css" media="print">

    <!-- Fonts -->
    <link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
    <link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800"
        rel="stylesheet" type="text/css">
    <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">

    <!-- Highlight.js Stylesheets -->
    <link rel="stylesheet" href="../highlight.css">
    <link rel="stylesheet" href="../tomorrow-night.css">
    <link rel="stylesheet" href="../ayu-highlight.css">

    <!-- Custom theme stylesheets -->
    
    <link rel="stylesheet" href="../theme/custom.css">
    

    
</head>

<body class="light">
    <!-- Provide site root to javascript -->
    <script type="text/javascript">var path_to_root = "../";</script>

    <!-- Work around some values being stored in localStorage wrapped in quotes -->
    <script type="text/javascript">
        try {
            var theme = localStorage.getItem('mdbook-theme');
            var sidebar = localStorage.getItem('mdbook-sidebar');

            if (theme.startsWith('"') && theme.endsWith('"')) {
                localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
            }

            if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
            }
        } catch (e) { }
    </script>

    <!-- Set the theme before any content is loaded, prevents flash -->
    <script type="text/javascript">
        var theme;
        try { theme = localStorage.getItem('mdbook-theme'); } catch (e) { }
        if (theme === null || theme === undefined) { theme = 'light'; }
        document.body.className = theme;
        document.querySelector('html').className = theme + ' js';
    </script>

    <!-- Hide / unhide sidebar before it is displayed -->
    <script type="text/javascript">
        var html = document.querySelector('html');
        var sidebar = 'hidden';
        if (document.body.clientWidth >= 1080) {
            try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch (e) { }
            sidebar = sidebar || 'visible';
        }
        html.classList.remove('sidebar-visible');
        html.classList.add("sidebar-" + sidebar);
    </script>

    <nav id="sidebar" class="sidebar" aria-label="Table of contents">
        <ol class="chapter"><li><a href="../index.html"><strong aria-hidden="true">1.</strong> 超过 88 道练习，任点</a></li><li><a href="../low.html"><strong aria-hidden="true">2.</strong> 易</a></li><li><ol class="section"><li><a href="../hello-world/README.zh.html"><strong aria-hidden="true">2.1.</strong> hello world</a></li><li><a href="../gigasecond/README.zh.html"><strong aria-hidden="true">2.2.</strong> 千兆秒 &gt;&lt; Gigasecond)</a></li><li><a href="../leap/README.zh.html"><strong aria-hidden="true">2.3.</strong> 闰年 &gt;&lt; Leap</a></li><li><a href="../raindrops/README.zh.html"><strong aria-hidden="true">2.4.</strong> 雨滴声 &gt;&lt; Raindrops</a></li><li><a href="../reverse-string/README.zh.html"><strong aria-hidden="true">2.5.</strong> 反转字符串 &gt;&lt; Reverse String</a></li><li><a href="../nth-prime/README.zh.html"><strong aria-hidden="true">2.6.</strong> 第 n 个素数 &gt;&lt; Nth Prime</a></li><li><a href="../bob/README.zh.html"><strong aria-hidden="true">2.7.</strong> 迟钝孩子 &gt;&lt; Bob</a></li><li><a href="../beer-song/README.zh.html"><strong aria-hidden="true">2.8.</strong> 啤酒之歌 &gt;&lt; Beer Song</a></li><li><a href="../proverb/README.zh.html"><strong aria-hidden="true">2.9.</strong> 谚语串烧 &gt;&lt; Proverb</a></li><li><a href="../difference-of-squares/README.zh.html"><strong aria-hidden="true">2.10.</strong> 平方差 &gt;&lt; Difference Of Squares</a></li><li><a href="../sum-of-multiples/README.zh.html"><strong aria-hidden="true">2.11.</strong> 倍数之和 &gt;&lt; Sum Of Multiples</a></li><li><a href="../grains/README.zh.html"><strong aria-hidden="true">2.12.</strong> 谷物 &gt;&lt; Grains</a></li><li><a href="../pythagorean-triplet/README.zh.html"><strong aria-hidden="true">2.13.</strong> 勾股数 &gt;&lt; Pythagorean Triplet</a></li><li><a href="../prime-factors/README.zh.html"><strong aria-hidden="true">2.14.</strong> 素数因子 &gt;&lt; Prime Factors</a></li><li><a href="../series/README.zh.html"><strong aria-hidden="true">2.15.</strong> 子串 &gt;&lt; Series</a></li><li><a href="../armstrong-numbers/README.zh.html"><strong aria-hidden="true">2.16.</strong> 水仙花数 &gt;&lt; Armstrong Numbers</a></li><li><a href="../collatz-conjecture/README.zh.html"><strong aria-hidden="true">2.17.</strong> 3n+1 猜想 &gt;&lt; Collatz Conjecture</a></li><li><a href="../diffie-hellman/README.zh.html"><strong aria-hidden="true">2.18.</strong> 迪菲-赫尔曼密钥交换 &gt;&lt; Diffie Hellman</a></li></ol></li><li><a href="../medium.html"><strong aria-hidden="true">3.</strong> 中等</a></li><li><ol class="section"><li><a href="../saddle-points/README.zh.html"><strong aria-hidden="true">3.1.</strong> 鞍点 &gt;&lt; Saddle Points</a></li><li><a href="../isogram/README.zh.html"><strong aria-hidden="true">3.2.</strong> 等值线 &gt;&lt; Isogram</a></li><li><a href="../say/README.zh.html"><strong aria-hidden="true">3.3.</strong> 英文说数字 &gt;&lt; Say</a></li><li><a href="../run-length-encoding/README.zh.html"><strong aria-hidden="true">3.4.</strong> 游程编码 &gt;&lt; Run Length Encoding</a></li><li><a href="../isbn-verifier/README.zh.html"><strong aria-hidden="true">3.5.</strong> 图书编号 &gt;&lt; ISBN Verifier</a></li><li><a href="../perfect-numbers/README.zh.html"><strong aria-hidden="true">3.6.</strong> 数字也能分类 &gt;&lt; Perfect Numbers</a></li><li><a href="../clock/README.zh.html"><strong aria-hidden="true">3.7.</strong> 时钟 &gt;&lt; Clock</a></li><li><a href="../dot-dsl/README.zh.html"><strong aria-hidden="true">3.8.</strong> DOT DSL</a></li><li><a href="../hamming/README.zh.html"><strong aria-hidden="true">3.9.</strong> 汉明距离 &gt;&lt; Hamming</a></li><li><a href="../simple-linked-list/README.zh.html"><strong aria-hidden="true">3.10.</strong> 简单链表 &gt;&lt; Simple Linked List</a></li><li><a href="../pascals-triangle/README.zh.html"><strong aria-hidden="true">3.11.</strong> 杨辉三角形 &gt;&lt; Pascal's Triangle</a></li><li><a href="../scrabble-score/README.zh.html"><strong aria-hidden="true">3.12.</strong> 字母的分数游戏 &gt;&lt; Scrabble Score</a></li><li><a href="../pangram/README.zh.html"><strong aria-hidden="true">3.13.</strong> 全字母句 &gt;&lt; Pangram</a></li><li><a href="../paasio/README.zh.html"><strong aria-hidden="true">3.14.</strong> PaaS-IO-报告 &gt;&lt; Paasio</a></li><li><a href="../nucleotide-count/README.zh.html"><strong aria-hidden="true">3.15.</strong> 核苷酸计数 &gt;&lt; Nucleotide Count</a></li><li><a href="../luhn/README.zh.html"><strong aria-hidden="true">3.16.</strong> 模 10 算法 &gt;&lt; Luhn</a></li><li><a href="../largest-series-product/README.zh.html"><strong aria-hidden="true">3.17.</strong> 最大数字子串乘积 &gt;&lt; Largest Series Product</a></li><li><a href="../word-count/README.zh.html"><strong aria-hidden="true">3.18.</strong> 单词计数 &gt;&lt; Word Count</a></li><li><a href="../atbash-cipher/README.zh.html"><strong aria-hidden="true">3.19.</strong> Atbash 加密 &gt;&lt; Atbash Cipher</a></li><li><a href="../crypto-square/README.zh.html" class="active"><strong aria-hidden="true">3.20.</strong> 密码矩形 &gt;&lt; Crypto Square</a></li><li><a href="../rotational-cipher/README.zh.html"><strong aria-hidden="true">3.21.</strong> 旋转密码 &gt;&lt; Rotational Cipher</a></li><li><a href="../simple-cipher/README.zh.html"><strong aria-hidden="true">3.22.</strong> 简单加密 &gt;&lt; Simple Cipher</a></li><li><a href="../rail-fence-cipher/README.zh.html"><strong aria-hidden="true">3.23.</strong> 栅栏密码 &gt;&lt; Rail Fence Cipher</a></li><li><a href="../etl/README.zh.html"><strong aria-hidden="true">3.24.</strong> ETL</a></li><li><a href="../accumulate/README.zh.html"><strong aria-hidden="true">3.25.</strong> 集合操作 &gt;&lt; Accumulate</a></li><li><a href="../acronym/README.zh.html"><strong aria-hidden="true">3.26.</strong> 术语 &gt;&lt; Acronym</a></li><li><a href="../sieve/README.zh.html"><strong aria-hidden="true">3.27.</strong> 素数筛 &gt;&lt; Sieve</a></li><li><a href="../rna-transcription/README.zh.html"><strong aria-hidden="true">3.28.</strong> RNA 转录 &gt;&lt; RNA Transcription</a></li><li><a href="../triangle/README.zh.html"><strong aria-hidden="true">3.29.</strong> 三角形</a></li><li><a href="../roman-numerals/README.zh.html"><strong aria-hidden="true">3.30.</strong> 罗马数字 &gt;&lt; Roman Numerals</a></li><li><a href="../all-your-base/README.zh.html"><strong aria-hidden="true">3.31.</strong> 你所的基本</a></li><li><a href="../grade-school/README.zh.html"><strong aria-hidden="true">3.32.</strong> 学册</a></li><li><a href="../binary-search/README.zh.html"><strong aria-hidden="true">3.33.</strong> 二分查找</a></li><li><a href="../robot-simulator/README.zh.html"><strong aria-hidden="true">3.34.</strong> 机器人模拟器</a></li><li><a href="../bracket-push/README.zh.html"><strong aria-hidden="true">3.35.</strong> 括号配套</a></li><li><a href="../luhn-from/README.zh.html"><strong aria-hidden="true">3.36.</strong> Luhn From</a></li><li><a href="../queen-attack/README.zh.html"><strong aria-hidden="true">3.37.</strong> 皇后 攻击</a></li><li><a href="../bowling/README.zh.html"><strong aria-hidden="true">3.38.</strong> 保龄球</a></li><li><a href="../sublist/README.zh.html"><strong aria-hidden="true">3.39.</strong> 子列表</a></li><li><a href="../space-age/README.zh.html"><strong aria-hidden="true">3.40.</strong> 地球年</a></li><li><a href="../luhn-trait/README.zh.html"><strong aria-hidden="true">3.41.</strong> Luhn Trait</a></li><li><a href="../macros/README.zh.html"><strong aria-hidden="true">3.42.</strong> 宏</a></li><li><a href="../allergies/README.zh.html"><strong aria-hidden="true">3.43.</strong> 过敏</a></li><li><a href="../variable-length-quantity/README.zh.html"><strong aria-hidden="true">3.44.</strong> 可变长度数量</a></li><li><a href="../phone-number/README.zh.html"><strong aria-hidden="true">3.45.</strong> 电话号码</a></li><li><a href="../wordy/README.zh.html"><strong aria-hidden="true">3.46.</strong> 罗唆</a></li><li><a href="../tournament/README.zh.html"><strong aria-hidden="true">3.47.</strong> 比赛</a></li><li><a href="../custom-set/README.zh.html"><strong aria-hidden="true">3.48.</strong> 自定义 set</a></li><li><a href="../alphametics/README.zh.html"><strong aria-hidden="true">3.49.</strong> 字母谜题</a></li><li><a href="../two-bucket/README.zh.html"><strong aria-hidden="true">3.50.</strong> 两个桶</a></li><li><a href="../pig-latin/README.zh.html"><strong aria-hidden="true">3.51.</strong> 猪的拉丁文</a></li><li><a href="../diamond/README.zh.html"><strong aria-hidden="true">3.52.</strong> 钻石</a></li><li><a href="../spiral-matrix/README.zh.html"><strong aria-hidden="true">3.53.</strong> 螺旋矩阵</a></li><li><a href="../palindrome-products/README.zh.html"><strong aria-hidden="true">3.54.</strong> 回文产品</a></li><li><a href="../poker/README.zh.html"><strong aria-hidden="true">3.55.</strong> 扑克</a></li><li><a href="../grep/README.zh.html"><strong aria-hidden="true">3.56.</strong> grep</a></li><li><a href="../scale-generator/README.zh.html"><strong aria-hidden="true">3.57.</strong> 音阶生成器</a></li><li><a href="../decimal/README.zh.html"><strong aria-hidden="true">3.58.</strong> 十进制</a></li><li><a href="../anagram/README.zh.html"><strong aria-hidden="true">3.59.</strong> 字谜</a></li><li><a href="../protein-translation/README.zh.html"><strong aria-hidden="true">3.60.</strong> 蛋白质翻译</a></li><li><a href="../robot-name/README.zh.html"><strong aria-hidden="true">3.61.</strong> 机器人名称</a></li><li><a href="../book-store/README.zh.html"><strong aria-hidden="true">3.62.</strong> 书店</a></li></ol></li><li><a href="../high.html"><strong aria-hidden="true">4.</strong> 难</a></li><li><ol class="section"><li><a href="../ocr-numbers/README.zh.html"><strong aria-hidden="true">4.1.</strong> OCR 号码</a></li><li><a href="../minesweeper/README.zh.html"><strong aria-hidden="true">4.2.</strong> 扫雷</a></li><li><a href="../dominoes/README.zh.html"><strong aria-hidden="true">4.3.</strong> 骨牌</a></li><li><a href="../parallel-letter-frequency/README.zh.html"><strong aria-hidden="true">4.4.</strong> 并行字母频率</a></li><li><a href="../rectangles/README.zh.html"><strong aria-hidden="true">4.5.</strong> 矩形</a></li><li><a href="../forth/README.zh.html"><strong aria-hidden="true">4.6.</strong> Forth</a></li><li><a href="../circular-buffer/README.zh.html"><strong aria-hidden="true">4.7.</strong> 循环缓冲区</a></li><li><a href="../react/README.zh.html"><strong aria-hidden="true">4.8.</strong> React</a></li></ol></li><li><a href="../untag.html"><strong aria-hidden="true">5.</strong> 未标签</a></li><li><ol class="section"><li><a href="../hexadecimal/README.zh.html"><strong aria-hidden="true">5.1.</strong> 十六进制</a></li><li><a href="../nucleotide-codons/README.zh.html"><strong aria-hidden="true">5.2.</strong> 核苷酸密码子</a></li><li><a href="../two-fer/README.zh.html"><strong aria-hidden="true">5.3.</strong> two-fer</a></li><li class="spacer"></li></ol></li><li><a href="../add-test-code.html">修改 mdBook 主题</a></li></ol>
    </nav>

    <div id="page-wrapper" class="page-wrapper">

        <div class="page">
            
            <div id="menu-bar" class="menu-bar">
                <div id="menu-bar-sticky-container">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents"
                            aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <!-- START - Rust Cookbook customization -->
                        <button id="edit-button" class="icon-button" type="button" title="Fork and edit" aria-label="Fork and edit"
                            aria-haspopup="true" aria-expanded="false" aria-controls="edit">
                            <i class="fa fa-edit">Edit</i>
                        </button>
                        <!-- END - Rust Cookbook customization -->
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme"
                            aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light <span class="default">(default)</span></button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)"
                            aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                        
                    </div>

                    <h1 class="menu-title">exercisms.io 快速练习</h1>
                    
                        <div class="right-buttons">
                            <a href="../print.html" title="Print this book" aria-label="Print this book">
                                <i id="print-button" class="fa fa-print"></i>
                            </a>
                            
                        </div>
                    </div>
                </div>

            
            <div id="search-wrapper" class="hidden">
                <form id="searchbar-outer" class="searchbar-outer">
                    <input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..."
                        aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                </form>
                <div id="searchresults-outer" class="searchresults-outer hidden">
                    <div id="searchresults-header" class="searchresults-header"></div>
                    <ul id="searchresults">
                    </ul>
                </div>
            </div>
            

            <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
            <script type="text/javascript">
                document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                Array.from(document.querySelectorAll('#sidebar a')).forEach(function (link) {
                    link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                });
            </script>

            <!-- // START - Rust Cookbook customization -->
            <script>
                document.getElementById("edit-button").addEventListener("click", function () {
                    var editWindow = window.open("https://github.com/chinanf-boy/exercism-rust-zh/edit/master/src/crypto-square/README.zh.md");
                });</script>
            <!-- // END - Rust Cookbook customization -->

            <div id="content" class="content">
                <main>
                    <a class="header" href="#crypto-square" id="crypto-square"><h1>Crypto Square</h1></a>
<a class="header" href="#1-readme" id="1-readme"><h2>1. Readme</h2></a>
<a class="header" href="#加密广场" id="加密广场"><h1>加密广场</h1></a>
<p>实现，用于组成称为方形代码的加密信息的经典方法.</p>
<p>给定英文文本,输出该文本的加密编码版本。</p>
<p>首先,输入被规范化:</p>
<ul>
<li>从英文文本中删除空格和标点符号,并且消息是朝下的.</li>
</ul>
<p>然后,</p>
<ul>
<li>规范化字符被分成行。当使用插入的换行符打印时,这些行自自然然形成类似矩形的样子。</li>
</ul>
<p>例如,句子</p>
<pre><code class="language-text">&quot;If man was meant to stay on the ground, god would have given us roots.&quot;
</code></pre>
<p>规范化为:</p>
<pre><code class="language-text">&quot;ifmanwasmeanttostayonthegroundgodwouldhavegivenusroots&quot;
</code></pre>
<p>明文应该组织成一个矩形。矩形的大小(<code>r x c</code>)应该根据消息的长度来决定<code>c &gt;= r</code>和<code>c - r &lt;= 1</code>,这里的<code>c</code>是列数和<code>r</code>是行数.</p>
<p>我们的标准化文本长度为 54 个字符，用<code>c = 8</code>和<code>r = 7</code>指示矩形:</p>
<pre><code class="language-text">&quot;ifmanwas&quot;
&quot;meanttos&quot;
&quot;tayonthe&quot;
&quot;groundgo&quot;
&quot;dwouldha&quot;
&quot;vegivenu&quot;
&quot;sroots  &quot;
</code></pre>
<p>通过向下(第一行第一个,拼接第二行第一个)，读取从左到右的列来获得编码消息.</p>
<p>上面的消息编码为:</p>
<pre><code class="language-text">&quot;imtgdvsfearwermayoogoanouuiontnnlvtwttddesaohghnsseoau&quot;
</code></pre>
<p>根据输出的，矩形块编码文本的大小<code>(r X c)</code>，表明有<code>c</code>块<code>r</code>长度的编码字串，以空格分隔。对于那些<code>n</code>位字符，但少于规定的长度的，每个尾添一个空格。</p>
<pre><code class="language-text">&quot;imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn  sseoau &quot;
</code></pre>
<p>请注意,如果我们要堆叠这些,我们可以直观地，将密文解码回原始消息:
(第一行第一个，拼接第二行第一个...)</p>
<pre><code class="language-text">&quot;imtgdvs&quot;
&quot;fearwer&quot;
&quot;mayoogo&quot;
&quot;anouuio&quot;
&quot;ntnnlvt&quot;
&quot;wttddes&quot;
&quot;aohghn &quot;
&quot;sseoau &quot;
</code></pre>
<a class="header" href="#资源" id="资源"><h2>资源</h2></a>
<p>J Dalbey 的编程实践问题<a href="http://users.csc.calpoly.edu/%7Ejdalbey/103/Projects/ProgrammingPractice.html">http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html</a></p>
<a class="header" href="#2-开始你的表演" id="2-开始你的表演"><h2>2. 开始你的表演</h2></a>
<pre><pre class="playpen"><code class="language-rust editable">pub fn encrypt(input: &amp;str) -&gt; String {
   unimplemented!(&quot;Encrypt {:?} using a square code&quot;, input)
}

</code></pre></pre>
<a class="header" href="#3-测试代码查看" id="3-测试代码查看"><h2>3. 测试代码查看</h2></a>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
fn test(input: &amp;str, output: &amp;str) {
   assert_eq!(&amp;encrypt(input), output);
}

#[test]
fn test_empty_input() {
   test(&quot;&quot;, &quot;&quot;)
}

#[test]
//#[ignore]
fn test_encrypt_also_decrypts_square() {
   // note that you only get the exact input back if:
   // 1. no punctuation
   // 2. even spacing
   // 3. all lowercase
   // 4. square input
   let example = &quot;lime anda coco anut&quot;;
   assert_eq!(example, &amp;encrypt(&amp;encrypt(example)));
}

#[test]
//#[ignore]
fn test_example() {
   test(
       &quot;If man was meant to stay on the ground, god would have given us roots.&quot;,
       &quot;imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn  sseoau &quot;,
   )
}

#[test]
//#[ignore]
fn test_empty_last_line() {
   test(&quot;congratulate&quot;, &quot;crl oaa ntt gue&quot;)
}

#[test]
//#[ignore]
fn test_spaces_are_reorganized() {
   test(&quot;abet&quot;, &quot;ae bt&quot;);
   test(&quot;a bet&quot;, &quot;ae bt&quot;);
   test(&quot;     a  b     e      t             &quot;, &quot;ae bt&quot;);
}

#[test]
//#[ignore]
fn test_everything_becomes_lowercase() {
   test(&quot;caSe&quot;, &quot;cs ae&quot;);
   test(&quot;cAsE&quot;, &quot;cs ae&quot;);
   test(&quot;CASE&quot;, &quot;cs ae&quot;);
}

#[test]
//#[ignore]
fn test_long() {
   test(
       r#&quot;
We choose to go to the moon.

We choose to go to the moon in this decade and do the other things,
not because they are easy, but because they are hard, because that
goal will serve to organize and measure the best of our energies and
skills, because that challenge is one that we are willing to accept,
one we are unwilling to postpone, and one which we intend to win,
and the others, too.

-- John F. Kennedy, 12 September 1962
       &quot;#,
       &amp;(String::from(&quot;womdbudlmecsgwdwob enooetbsenaotioihe &quot;)
           + &quot;cwotcbeeaeunolnnnr henhaecrsrsealeaf1 ocieucavugetciwnk9 &quot;
           + &quot;ohnosauerithcnhde6 sotteusteehaegitn2 eohhtseotsatptchn  &quot;
           + &quot;tsiehetohatwtohee  oesrethrenceopwod  gtdtyhagbdhanoety  &quot;
           + &quot;ooehaetaesaresih1  tgcirygnsklewtne2  ooaneaoitilweptrs  &quot;
           + &quot;ttdgerazoleiaoese  hoesaeleflnlrnntp  etanshwaosgleedot  &quot;
           + &quot;mhnoyainubeiuatoe  oedtbrldreinnnojm &quot;),
   )
}

#}</code></pre></pre>
<a class="header" href="#4-答案" id="4-答案"><h2>4. 答案</h2></a>
<p><details></p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
extern crate itertools;
use itertools::Itertools;

/// Encrypt the input string using square cryptography
pub fn encrypt(input: &amp;str) -&gt; String {
   let prepared = prepare(input);
   if prepared.len() == 0 {
       return String::new();
   }

   let (cols, rows) = dimensions(prepared.len());

   let mut output = String::with_capacity(input.len());
   for chunk_iterator in SquareIndexer::new(rows, cols).chunks(cols).into_iter() {
       for ch_idx in chunk_iterator {
           if ch_idx &lt; prepared.len() {
               output.push(prepared[ch_idx]);
           }
       }
       output.push(' ');
   }

   // we know there's one extra space at the end
   output.pop();

   output
}

/// Construct a vector of characters from the given input.
///
/// Constrain it to the allowed chars: lowercase ascii letters.
/// We construct a vector here because the length of the input
/// matters when constructing the output, so we need to know
/// how many input chars there are. We could treat it as a stream
/// and just stream twice, but collecting it into a vector works
/// equally well and might be a bit faster.
fn prepare(input: &amp;str) -&gt; Vec&lt;char&gt; {
   let mut output = Vec::with_capacity(input.len());

   output.extend(
       input
           .chars()
           .filter(|&amp;c| c.is_ascii() &amp;&amp; !c.is_whitespace() &amp;&amp; !c.is_ascii_punctuation())
           .map(|c| c.to_ascii_lowercase()),
   );

   // add space padding to the end such that the actual string returned
   // forms a perfect rectangle
   let (r, c) = dimensions(output.len());
   let padding_qty = (r * c) - output.len();
   for _ in 0..padding_qty {
       output.push(' ');
   }

   output.shrink_to_fit();

   output
}

/// Get the dimensions of the appropriate bounding rectangle for this encryption
///
/// To find `(rows, cols)` such that `cols &gt;= rows &amp;&amp; cols - rows &lt;= 1`, we find
/// the least square greater than or equal to the message length. Its square root
/// is the cols. If the message length is a perfect square, `rows` is the same.
/// Otherwise, it is one less.
fn dimensions(length: usize) -&gt; (usize, usize) {
   let cols = (length as f64).sqrt().ceil() as usize;
   let rows = if cols * cols == length {
       cols
   } else {
       cols - 1
   };
   (rows, cols)
}

/// Iterator over the indices of the appropriate chars of the output.
///
/// For a (2, 3) (r, c) grid, yields (0, 3, 1, 4, 2, 5).
/// Does no bounds checking or space insertion: that's handled elsewhere.
#[derive(Debug)]
struct SquareIndexer {
   rows: usize,
   cols: usize,
   cur_row: usize,
   cur_col: usize,
   max_value: usize,
}

impl SquareIndexer {
   fn new(rows: usize, cols: usize) -&gt; SquareIndexer {
       SquareIndexer {
           rows: rows,
           cols: cols,
           cur_row: 0,
           cur_col: 0,
           max_value: rows * cols,
       }
   }
}

impl Iterator for SquareIndexer {
   type Item = usize;
   fn next(&amp;mut self) -&gt; Option&lt;usize&gt; {
       let value = self.cur_row + (self.cur_col * self.rows);
       let output = if value &lt; self.max_value &amp;&amp; self.cur_row &lt; self.rows {
           Some(value)
       } else {
           None
       };

       // now increment internal state to next value
       self.cur_col += 1;
       if self.cur_col &gt;= self.cols {
           self.cur_col = 0;
           self.cur_row += 1;
       }

       output
   }
}

#}</code></pre></pre>
<p></details></p>
<hr />
<hr />
<a class="header" href="#填充相关" id="填充相关"><h2>填充/相关</h2></a>

                </main>

                <nav class="nav-wrapper" aria-label="Page navigation">
                    <!-- Mobile navigation buttons -->
                    
                    <a rel="prev" href="../atbash-cipher/README.zh.html" class="mobile-nav-chapters previous" title="Previous chapter"
                        aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>
                    

                    
                    <a rel="next" href="../rotational-cipher/README.zh.html" class="mobile-nav-chapters next" title="Next chapter"
                        aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
                    

                    <div style="clear: both"></div>
                </nav>
            </div>
        </div>

        <nav class="nav-wide-wrapper" aria-label="Page navigation">
            
            <a href="../atbash-cipher/README.zh.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter"
                aria-keyshortcuts="Left">
                <i class="fa fa-angle-left"></i>
            </a>
            

            
            <a href="../rotational-cipher/README.zh.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter"
                aria-keyshortcuts="Right">
                <i class="fa fa-angle-right"></i>
            </a>
            
        </nav>

    </div>

    

    
    <!-- Google Analytics Tag -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-128555056-1"></script>
    
    <script type="text/javascript">
        var localAddrs = ["localhost", "127.0.0.1", ""];
        if (localAddrs.indexOf(document.location.hostname) === -1) {
            window.dataLayer = window.dataLayer || [];
            function gtag() { dataLayer.push(arguments); }
            gtag('js', new Date());

            gtag('config', 'UA-128555056-1');
        }
    </script>
    

    
    <script src="../ace.js" type="text/javascript" charset="utf-8"></script>
    <script src="../editor.js" type="text/javascript" charset="utf-8"></script>
    <script src="../mode-rust.js" type="text/javascript" charset="utf-8"></script>
    <script src="../theme-dawn.js" type="text/javascript" charset="utf-8"></script>
    <script src="../theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
    

    
    <script src="../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="../mark.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="../searcher.js" type="text/javascript" charset="utf-8"></script>
    

    <script src="../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="../highlight.js" type="text/javascript" charset="utf-8"></script>
    <script src="../book.js" type="text/javascript" charset="utf-8"></script>

    <!-- Custom JS scripts -->
    

    

</body>

</html>